<?php

if(!defined('IN_PROJECTOR')) exit('Access Denied');

class Admin{
	public $v = array();	//用户信息，用于修改
	private $o = array();	//原始用户信息，用于判断信息是否被修改和更新数据库
	private $logged = false;
	
	static private $perms = array('all' => 0x1, 'addproject' => 0x2, 'editproject' => 0x4, 'deleteproject' => 0x8, 'addprocess' => 0x10, 'deleteprocess' => 0x20);

	public function __construct($uid = 0){
		global $db;

		if($uid){
			$db->select_table('administrator');
			$this->o = $this->v = $db->FETCH('*', 'uid='.$uid);
		}
	}
	
	public function __destruct(){
		global $db;
		if($this->o['uid']){
			$update = array_diff_update($this->o, $this->v);
			unset($update['uid']);
			if($update){
				$db->select_table('administrator');
				$db->UPDATE($update, 'uid='.$this->o['uid']);
			}
		}
	}

	public function login($name, $pw = '', $method = ''){
		global $db, $tpre;
		if(!$pw){//Login by Cookie
			$v = $this->decodeCookie($name);
			
			if(!$v || !$v['uid'] || !$v['pwmd5']){
				$this->logout();
				return false;
			}
			
			$this->v = $db->fetch_first("SELECT * FROM {$tpre}administrator WHERE uid=$v[uid] AND pwmd5='$v[pwmd5]'");
		}else{
			if(!$method){
				if(strpos('@', $name) !== false){
					$method = 'email';
				}elseif(!in_array($method, array('uid', 'username', 'email'))){
					$method = 'uid';
				}
			}else if(!in_array($method, array('uid','email','username'))){
				$method = 'username';
			}
			$pwmd5 = rmd5($pw);
			$this->v = $db->fetch_first("SELECT * FROM {$tpre}administrator WHERE `$method`='$name' AND pwmd5='$pwmd5'");
		}

		if(!$this->v){
			$this->logout();
			return false;
		}else{
			$this->logged = true;
			rsetcookie('rcuserinfo', $this->encodeCookie());
			$this->o = $this->v;
			
			if($pw){
				$this->v['lastlogin'] = $this->v['logintime'];
				$this->v['logintime'] = $GLOBALS['_G']['timestamp'];
				$this->v['ip'] = $this->ip();
			}
			
			return true;
		}
	}
	
	public function logout(){
		rsetcookie('rcuserinfo');
	}
	
	public function isLogged(){
		return $this->logged;
	}
	
	public function isSuperAdmin(){
		return ($this->v['permission'] & 0x1) == 0x1;
	}
	
	public function register(){
		global $db;
		
		if(!$this->v['username']){
			return -1;
		}
		
		$this->v['pwmd5'] = rmd5($this->v['password']);
		unset($this->v['password']);
		
		$db->select_table('administrator');
		$db->INSERT($this->v);
		
		return $db->insert_id();
	}
	
	public function changePassword($old, $new, $new2){
		if(!$this->v['uid']){
			return -3;
		}elseif(rmd5($old) != $this->v['pwmd5']){
			return -1;
		}elseif($new != $new2){
			return -2;
		}
		
		$this->v['pwmd5'] = rmd5($new);
		rsetcookie('rcuserinfo', $this->encodeCookie());

		return true;
	}
	
	public function ip(){
		$onlineip = '0.0.0.0';
		if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
			$onlineip = getenv('HTTP_CLIENT_IP');
		} elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
			$onlineip = getenv('HTTP_X_FORWARDED_FOR');
		} elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
			$onlineip = getenv('REMOTE_ADDR');
		} elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
			$onlineip = $_SERVER['REMOTE_ADDR'];
		}
		return $onlineip;
	}
	
	public function uploadAvatar($file){
		global $_G, $db;
	
		if(!is_array($file)){
			return false;
		}

		$info = pathinfo($file['name']);
		$info['extension'] = strtolower($info['extension']);
		$extension = in_array($info['extension'], array('jpg', 'jpeg', 'png', 'gif')) ? $info['extension'] : 'attach';
		if($extension == 'attach'){
			return false;
		}
		$this->v['avatar'] = './data/avatar/'.$this->v['uid'].'.'.$extension;

		if(!move_uploaded_file($file['tmp_name'], S_ROOT.$this->v['avatar'])){
			return false;
		}
		
		list($old_width, $old_height) = getimagesize(S_ROOT.$this->v['avatar']);
		$new_width = 120;
		$new_height = 120;

		// Resample
		$newimg = imagecreatetruecolor($new_width, $new_height);
		$func = 'imagecreatefrom'.($extension == 'jpg' ? 'jpeg' : $extension);
		$oldimg = $func(S_ROOT.$this->v['avatar']);
		imagecopyresampled($newimg, $oldimg, 0, 0, 0, 0, $new_width, $new_height, $old_width, $old_height);
		$func = 'image'.($extension == 'jpg' ? 'jpeg' : $extension);
		$func($newimg, S_ROOT.$this->v['avatar']);

		return true;
	}
	
	public function hasPermission($permission){
		if(isset(self::$perms[$permission])){
			return $this->isSuperAdmin() || ($this->v['permission'] & self::$perms[$permission]) == self::$perms[$permission];
		}else{
			return false;
		}
	}
	
	public function setPermission($permission, $value = true){
		if(!is_array($permission)){
			if(isset(self::$perms[$permission])){
				if($value){
					$this->v['permission'] |= self::$perms[$permission];
				}else{
					$this->v['permission'] &= ~$value;
				}
				return true;
			}else{
				return false;
			}
		}else{
			$this->v['permission'] = $this->isSuperAdmin() ? 0x1 : 0x0;
			foreach(self::$perms as $p => $c){
				if($permission[$p]){
					$this->v['permission'] |= $c;
				}
			}
			return true;
		}
	}
	
	static public function getAdminList($offset, $limit){
		global $db;
		$db->select_table('administrator');
		return $db->MFETCH('*', "1 LIMIT $offset,$limit");
	}
	
	static public function getAdminNum(){
		global $db, $tpre;
		return $db->result_first("SELECT COUNT(*) FROM {$tpre}administrator WHERE 1");
	}
	
	static public function deleteAdmin($uid){
		global $db;
		
		if(!$uid = intval($uid)){
			return -1;
		}
		
		$db->select_table('administrator');
		$db->DELETE('uid='.$uid.' AND MOD(permission,2)!=1');
		return $db->affected_rows();
	}

	private function decodeCookie($auth){
		return unserialize($this->authcode($auth, 'DECODE', $GLOBALS['_G']['setting']['halt']));
	}
	
	private function encodeCookie(){
		return $this->authcode(serialize($this->v), 'ENCODE', $GLOBALS['_G']['setting']['halt']);
	}
	
	private function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
		$ckey_length = 4;
		$keya = md5(substr($key, 0, 16));
		$keyb = md5(substr($key, 16, 16));
		$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
	
		$cryptkey = $keya.md5($keya.$keyc);
		$key_length = strlen($cryptkey);
	
		$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
		$string_length = strlen($string);
	
		$result = '';
		$box = range(0, 255);
	
		$rndkey = array();
		for($i = 0; $i <= 255; $i++) {
			$rndkey[$i] = ord($cryptkey[$i % $key_length]);
		}
	
		for($j = $i = 0; $i < 256; $i++) {
			$j = ($j + $box[$i] + $rndkey[$i]) % 256;
			$tmp = $box[$i];
			$box[$i] = $box[$j];
			$box[$j] = $tmp;
		}
	
		for($a = $j = $i = 0; $i < $string_length; $i++) {
			$a = ($a + 1) % 256;
			$j = ($j + $box[$a]) % 256;
			$tmp = $box[$a];
			$box[$a] = $box[$j];
			$box[$j] = $tmp;
			$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
		}
	
		if($operation == 'DECODE') {
			if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
				return substr($result, 26);
			} else {
				return '';
			}
		} else {
			return $keyc.str_replace('=', '', base64_encode($result));
		}
	}

}
?>